/***
 * Modify Histroy
 * NO.01 2014/12/18  如果玻璃ID重复,用玻璃ID+内部订单ID 生成一笔新的记录,fab_sn(实际玻璃)用原玻璃ID记录,便于后续追溯
 */
package com.service;

import static com.def.GenericDef.BANK_OUT;
import static com.def.GenericDef.EMPTY_CARRIER;
import static com.def.GenericDef.EVT_CANCEL_UNPACK;
import static com.def.GenericDef.EVT_STB_INPR;
import static com.def.GenericDef.EVT_WIP_RETAIN;
import static com.def.GenericDef.EXIST_CARRIER;
import static com.def.GenericDef.E_BIS_MDL_DEF;
import static com.def.GenericDef.E_BIS_PATH;
import static com.def.GenericDef.E_BIS_TOOL_GR;
import static com.def.GenericDef.E_READ_NOT_FOUND;
import static com.def.GenericDef.E_RET_BOX;
import static com.def.GenericDef.E_RET_PRD_IN;
import static com.def.GenericDef.E_RET_PRD_INFO;
import static com.def.GenericDef.E_RET_WO;
import static com.def.GenericDef.E_XPUNPACK_BOX_CNT_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_BOX_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_BOX_IS_FULL;
import static com.def.GenericDef.E_XPUNPACK_CANCEL_PRD_INFO_CR_PROC_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_CANCEL_PRD_INFO_STATUS_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_INVALID_BOX_ID;
import static com.def.GenericDef.E_XPUNPACK_INVALID_BOX_STATUS;
import static com.def.GenericDef.E_XPUNPACK_INVALID_CUS_ID;
import static com.def.GenericDef.E_XPUNPACK_INVALID_INPUT;
import static com.def.GenericDef.E_XPUNPACK_INVALID_PRD_ID;
import static com.def.GenericDef.E_XPUNPACK_INVALID_WO_COUNT;
import static com.def.GenericDef.E_XPUNPACK_INVALID_WO_STATUS;
import static com.def.GenericDef.E_XPUNPACK_MTRL_BOX_ALREADY_EMPT;
import static com.def.GenericDef.E_XPUNPACK_MTRL_BOX_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_PRD_INFO_EXIST;
import static com.def.GenericDef.E_XPUNPACK_PRD_IN_NOT_ENOUGH;
import static com.def.GenericDef.E_XPUNPACK_REAL_EMPT_FLG_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_SLOT_NO_IN_MTRL_EXIST;
import static com.def.GenericDef.PATH_IS_FINISH;
import static com.def.GenericDef.PRD_TYPE_SHEET;
import static com.def.GenericDef.PROC_EMPTY;
import static com.def.GenericDef.PROC_IN_PROCESS;
import static com.def.GenericDef.PROC_RELS;
import static com.def.GenericDef.PROC_WAIT;
import static com.def.GenericDef.PROC_WFRL;
import static com.def.GenericDef.RETURN_CODE_OK;
import static com.def.GenericDef.RETURN_CODE_SET_ERROR;
import static com.def.GenericDef.RETURN_CODE_UNKNOWN;
import static com.def.GenericDef.RETURN_MESG_OK;
import static com.def.GenericDef.SHT_CR_PROC_ID_MIX;
import static com.def.GenericDef.SHT_MDL_CATE_MIX;
import static com.def.GenericDef.SHT_MDL_ID_MIX;
import static com.def.GenericDef.SHT_MDL_TYPE_MIX;
import static com.def.GenericDef.SHT_NX_PROC_ID_MIX;
import static com.def.GenericDef.SHT_NX_TOOLG_MIX;
import static com.def.GenericDef.SHT_OPE_ID_MIX;
import static com.def.GenericDef.SHT_OPE_NO_MIX;
import static com.def.GenericDef.SHT_OPE_VER_MIX;
import static com.def.GenericDef.SHT_PATH_ID_MIX;
import static com.def.GenericDef.SHT_PATH_VER_MIX;
import static com.def.GenericDef.SHT_WO_ID_MIX;
import static com.def.GenericDef.TRX_OUT;
import static com.def.GenericDef.T_XPUNPACK;
import static com.def.GenericDef.WIP_REATIN;
import static com.def.GenericDef.WO_STATUS_CLOS;
import static com.def.GenericDef._NO;
import static com.def.GenericDef._NO1_50;
import static com.def.GenericDef._NORMAL;
import static com.def.GenericDef._OK;
import static com.def.GenericDef._SPACE;
import static com.def.GenericDef._YES;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dao.IBisDataDao;
import com.dao.IBisMdlDefDao;
import com.dao.IBisOpeDao;
import com.dao.IBisPathDao;
import com.dao.IBisPathiDao;
import com.dao.IBisToolDao;
import com.dao.IBisToolGrDao;
import com.dao.IRetBoxDao;
import com.dao.IRetCusPrdInDao;
import com.dao.IRetCusPrdIndtDao;
import com.dao.IRetPrdGrdInfoDao;
import com.dao.IRetPrdInDao;
import com.dao.IRetPrdIndtDao;
import com.dao.IRetPrdInfoDao;
import com.dao.IRetPrdJgeDao;
import com.dao.IRetPrdLotDao;
import com.dao.IRetTmCusPrdInDao;
import com.dao.IRetTmCusPrdIndtDao;
import com.dao.IRetWODao;
import com.icim.service.ICIMBaseService;
import com.model.Bis_data;
import com.model.Bis_mdl_def;
import com.model.Bis_ope;
import com.model.Bis_opeId;
import com.model.Bis_path;
import com.model.Bis_pathId;
import com.model.Bis_pathi;
import com.model.Bis_pathiId;
import com.model.Bis_tool_gr;
import com.model.Bis_tool_grId;
import com.model.Ret_box;
import com.model.Ret_cus_prd_in;
import com.model.Ret_cus_prd_indt;
import com.model.Ret_prd_grd_info;
import com.model.Ret_prd_in;
import com.model.Ret_prd_inId;
import com.model.Ret_prd_indt;
import com.model.Ret_prd_indtId;
import com.model.Ret_prd_info;
import com.model.Ret_prd_lot;
import com.model.Ret_tm_cus_prd_in;
import com.model.Ret_tm_cus_prd_indt;
import com.model.Ret_wo;
import com.rtnBean.NotFoundRtnBeen;
import com.rtnBean.RouteObj;
import com.rtnBean.SimpleRtnBeen;
import com.tx.Xpunpack.XpunpackI;
import com.tx.Xpunpack.XpunpackO;
import com.util.GUIDGenerator;
import com.util.MqOpe;
import com.util.Util;

@Scope("prototype")
@Service("XpunpackService")
public class XpunpackService extends ICIMBaseService{
	private static final int RETURN_SHT_ID_BY_WO = 9;
	private Logger logger = Logger.getLogger(XpunpackService.class);
	private static String TX_NAME = T_XPUNPACK;

	private XpunpackI inTrx;
	private XpunpackO outTrx;
	private MqOpe mqOpe;

	private String gszMsgBuf = "";
	private Timestamp gEvtTimestamp;
	private Double gEvtTimeD;
	private String gEvtSeqID;
	/**
	 * 判断是否是最后一站
	 */
	private long last_ope = 0000000;
	@Autowired
	private IBisDataDao bisDataDao;
	@Autowired
	private IBisToolDao bisToolDao;
	@Autowired
	private IRetPrdInDao retPrdInDao;
	@Autowired
	private IRetPrdIndtDao retPrdIndtDao;
	@Autowired
	private IRetBoxDao retBoxDao;
	@Autowired
	private IRetPrdInfoDao retPrdInfoDao;
	@Autowired
	private IRetWODao retWoDao;
	@Autowired
	private IBisMdlDefDao bisMdlDefDao;
	@Autowired
	private IBisOpeDao bisOpeDao;
	@Autowired
	private IBisPathDao bisPathDao;
	@Autowired
	private IBisPathiDao bisPathiDao;
	@Autowired
	private IRetPrdJgeDao retPrdJgeDao;
	@Autowired
	private IBisToolGrDao bisToolGrDao;
	@Autowired
	private IRetPrdGrdInfoDao retPrdGrdInfoDao;
	@Autowired
	private IRetCusPrdIndtDao retCusPrdIndtDao;
	@Autowired
	private IRetCusPrdInDao retCusPrdInDao;
	@Autowired
	private IRetPrdLotDao retPrdLotDao;
	@Autowired
	private IRetTmCusPrdInDao retTmCusPrdInDao;
	@Autowired
	private IRetTmCusPrdIndtDao retTmCusPrdIndtDao;
	
	
	public String subMainProc(String strInMsg) {
		Session session = retPrdInfoDao.getCrSession();

		long rtnCode = _NORMAL;
		String outMsg = null;
		gszMsgBuf = "";
		gEvtTimestamp = Util.getCurrentTimestamp();
		gEvtTimeD = Util.getDoubleTime();
		gEvtSeqID = GUIDGenerator.javaGUID();

		inTrx = new XpunpackI();
		outTrx = new XpunpackO();
		outTrx.setTrx_id(TX_NAME);
		outTrx.setType_id(TRX_OUT);
		outTrx.setRtn_code(String.valueOf(RETURN_CODE_SET_ERROR));
		mqOpe = new MqOpe();

		try {
			inTrx = (XpunpackI) mqOpe.inStr2Obj(strInMsg, inTrx);
			logger.info("InTrx is " + strInMsg);

			rtnCode = subMainProc2(inTrx.getAction_flg().toCharArray()[0]);
			if (rtnCode != _NORMAL) {
				TransactionAspectSupport.currentTransactionStatus()
						.setRollbackOnly();
				outTrx.setRtn_code(String.valueOf(rtnCode));
				outTrx.setRtn_mesg(gszMsgBuf);
			} else {
				outTrx.setRtn_code(String.valueOf(RETURN_CODE_OK));
				outTrx.setRtn_mesg(RETURN_MESG_OK);
				session.flush();
			}
		} catch (Exception ex) {
			TransactionAspectSupport.currentTransactionStatus()
					.setRollbackOnly();
			outTrx.setRtn_mesg(ex.toString());
			outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
			logger.error(Util.stackTraceToString(ex));
		} finally {
			outMsg = mqOpe.obj2Str(outTrx);
			logger.info(outMsg);
		}
		return outMsg;
	}

	private long subMainProc2(char actionType) {
		long lRc = _NORMAL;
		switch (actionType) {
		case 'U': {
			lRc = unpackOpe();
			break;
		}
		case 'C': {
			lRc = cancelUnpackOpe();
			break;
		}
		case 'M': {
			lRc = getMtrlBoxInfo();
			break;
		}
		case 'X':{
			lRc = checkXmtmPrdIndtProc();
			break;
		}
		default: {
			gszMsgBuf = "Invalide type input: [" + actionType + "]";
			return E_XPUNPACK_INVALID_INPUT;
		}
		}

		return lRc;
	}

	/**
	 * 查询来料箱号信息
	 * 
	 * @return
	 */
	private long getMtrlBoxInfo() {
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		Ret_prd_in ret_prd_in = new Ret_prd_in();

		rtnBeen = retPrdInDao.getRetPrdInByWoAndBox(inTrx.getWo_id(),
				inTrx.getMtrl_box_id());
		if (E_RET_PRD_IN + E_READ_NOT_FOUND == rtnBeen.getlRc()) {
			gszMsgBuf = "内部订单[" + inTrx.getWo_id() + "]中没有箱子["
					+ inTrx.getMtrl_box_id() + "]!";
			return rtnBeen.getlRc();
		} else {
			ret_prd_in = (Ret_prd_in) rtnBeen.getObj();
			outTrx.setRet_prd_in(ret_prd_in);
		}

		return _NORMAL;
	}

	/**
	 * Unpack by panel
	 * 
	 * @return
	 */
	private long unpackOpe() {
		long lRc;
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		Ret_wo ret_wo = new Ret_wo();
		Bis_mdl_def bis_mdl_def = new Bis_mdl_def();
		Ret_box ret_box = new Ret_box();
		Ret_prd_in ret_prd_in = new Ret_prd_in();
		Ret_prd_indt ret_prd_indt = new Ret_prd_indt();
		Ret_prd_info ret_prd_info = new Ret_prd_info();

		Bis_path bis_path = new Bis_path();
		Bis_ope bis_ope = new Bis_ope();
		Bis_path nx_bis_path = new Bis_path();
		Bis_ope nx_bis_ope = new Bis_ope();
		Ret_cus_prd_indt ret_cus_prd_indt = new Ret_cus_prd_indt();
		Ret_cus_prd_in ret_cus_prd_in = new Ret_cus_prd_in();
		//定义产品ID
		String prd_seq_id = "";
		
		//NO.01 定义fab_sn
		String fab_sn = "";

		// Check wo
		rtnBeen = woCheck(inTrx.getWo_id());
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_wo = (Ret_wo) rtnBeen.getObj();
		}

		// Check mdl info
		rtnBeen = bisMdlDefCheck(ret_wo);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			bis_mdl_def = (Bis_mdl_def) rtnBeen.getObj();
		}
		
		lRc = getMtrlBoxInfo();
		if (lRc != _NORMAL){
			return lRc;
		}

		// Check mtrl box / prd_in
		rtnBeen = retMtrlBoxCheck(ret_wo.getWo_id(), inTrx.getMtrl_box_id());
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_prd_in = (Ret_prd_in) rtnBeen.getObj();
		}

		// Check box
		rtnBeen = retBoxCheck(inTrx.getBox_id());
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_box = (Ret_box) rtnBeen.getObj();
		}

		/**
		 * 传入的产品ID为空时，自动生成ID（规则：玻璃ID=客户ID+内部订单号+0001流水号）
		 * 不为空则检查ID是否重复
		 */
		if(Util.isSpaceCheck(inTrx.getPrd_seq_id())){
			// Check prd_info
			prd_seq_id = creatPrd(ret_wo);
			fab_sn = prd_seq_id;
			logger.info(fab_sn);
		}else{		
//			if(ret_wo.getCus_id_fk().equals("088")){
//				prd_seq_id = inTrx.getPrd_seq_id().substring(0, inTrx.getPrd_seq_id().length()-1);
//			}else{
//				prd_seq_id = inTrx.getPrd_seq_id();
//			}
			prd_seq_id = inTrx.getPrd_seq_id();
			fab_sn = prd_seq_id;
			
			// Check prd_info
			rtnBeen = retPrdInfoCheck(prd_seq_id,ret_wo.getCus_id_fk());
			/*if(rtnBeen.getlRc()== RETURN_SHT_ID_BY_WO){
				//NO.02 如果玻璃ID重复,用玻璃ID+工单组合生成新的玻璃ID
				prd_seq_id = (String) rtnBeen.getObj();
			}else if (rtnBeen.getlRc() != _NORMAL ) {
				return rtnBeen.getlRc();
			}*/
			if (rtnBeen.getlRc() != _NORMAL ) {
				return rtnBeen.getlRc();
			}
		}
		
		// Check prd_indt
		rtnBeen = retPrdIndtCheck(prd_seq_id);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		}
		
		// Check ret_cus_prd_in
		rtnBeen = retCusPrdInCheck(ret_wo);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_cus_prd_in = (Ret_cus_prd_in) rtnBeen.getObj();
		}
		
		// Check ret_cus_prd_indt
		rtnBeen = retCusPrdIndtCheck(prd_seq_id, ret_wo);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_cus_prd_indt = (Ret_cus_prd_indt) rtnBeen.getObj();
		}
		
		// Get path info
		// RouteObj
		rtnBeen = getPathInfoByWo(ret_wo, bis_mdl_def);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			bis_path = ((RouteObj) rtnBeen.getObj()).getPath();
			bis_ope = ((RouteObj) rtnBeen.getObj()).getOpe();
		}

		// Get next path info
		// RouteObj
		rtnBeen = getNextPathInfo(bis_path, bis_ope);
		if (rtnBeen.getlRc() != _NORMAL) {
			if(PATH_IS_FINISH == rtnBeen.getlRc()){
				last_ope = PATH_IS_FINISH;
			}else{
				gszMsgBuf = ((RouteObj) rtnBeen.getObj()).getGszMsgBuf();
				return rtnBeen.getlRc();
			}
		} else {
			nx_bis_path = ((RouteObj) rtnBeen.getObj()).getPath();
			nx_bis_ope = ((RouteObj) rtnBeen.getObj()).getOpe();
		}

		// Check inTrx's tool_id => ope vs wo's start ope
		rtnBeen = chkInputToolVsWoIndo(bis_ope);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		}

		// Add prd_indt
		rtnBeen = addPrdIndtForUnpack(ret_prd_in, prd_seq_id, ret_cus_prd_indt);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_prd_indt = (Ret_prd_indt) rtnBeen.getObj();
		}

		// Add prd_info
		rtnBeen = addPrdInfoForUnpack(ret_box, ret_wo, bis_mdl_def, bis_path,
				bis_ope, nx_bis_path, nx_bis_ope, ret_prd_in,
				ret_prd_indt.getMtrl_slot_no(), prd_seq_id,fab_sn,
				ret_cus_prd_in);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_prd_info = (Ret_prd_info) rtnBeen.getObj();
		}

		//add prd_grd_info
		rtnBeen = addPrdGrdInfoForUnpack(ret_wo, prd_seq_id);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} 
		
		// Check mix
		rtnBeen = checkRetPrdInfoMix(ret_prd_info, ret_box, ret_wo);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		}

		// Update box
		rtnBeen = updateBoxInfo(ret_box, ret_wo, bis_mdl_def,
				ret_cus_prd_in);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_box = (Ret_box) rtnBeen.getObj();
		}

		// Update mtrl box / prd_in
		rtnBeen = updateMtrlBoxInfo(ret_prd_in);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_prd_in = (Ret_prd_in) rtnBeen.getObj();
		}

		// Update wo info
		rtnBeen = updateWoInfo(ret_wo);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_wo = (Ret_wo) rtnBeen.getObj();
		}

		// Set outTrx
		setOutTrx(ret_prd_indt, ret_prd_info, ret_box, ret_wo ,ret_prd_in);

		return _NORMAL;
	}

	/**
	 * 检查用户选择的机台是否和工单绑定的起始站点匹配
	 * 
	 * @param ret_wo
	 * @param bis_ope
	 * @return SimpleRtnBeen{bis_tool_gr}
	 */
	private SimpleRtnBeen chkInputToolVsWoIndo(Bis_ope bis_ope) {
		String toolG = bis_ope.getToolg_id();
		Bis_tool_gr bis_tool_gr = new Bis_tool_gr();
		Bis_tool_grId bis_tool_grId = new Bis_tool_grId();
		bis_tool_grId.setTool_id_fk(inTrx.getTool_id());
		bis_tool_grId.setToolg_id(toolG);
		bis_tool_gr = bisToolGrDao.get(bis_tool_grId);
		if (null == bis_tool_gr) {
			gszMsgBuf = new NotFoundRtnBeen(bis_tool_grId.toString(),
					Bis_tool_gr.class).toString();
			return new SimpleRtnBeen(E_BIS_TOOL_GR + E_READ_NOT_FOUND);
		}

		return new SimpleRtnBeen(bis_tool_gr);
	}

	/**
	 * Check wo info for unpack panel
	 * 
	 * @return
	 */
	private SimpleRtnBeen woCheck(String wo_id) {
		Ret_wo ret_wo = new Ret_wo();

		// Check wo stutas and count
		ret_wo = retWoDao.getWithLock(wo_id, LockMode.UPGRADE);
		if (null == ret_wo) {
			gszMsgBuf = "内部订单 [" + wo_id + "] 不存在!";
			return new SimpleRtnBeen(E_RET_WO + E_READ_NOT_FOUND);
		} else {
			if (WO_STATUS_CLOS.equals(ret_wo.getWo_stat())) {
				gszMsgBuf = "内部订单 [" + ret_wo.getWo_id() + "] 已经关闭!";
				return new SimpleRtnBeen(E_XPUNPACK_INVALID_WO_STATUS);
			}
			if (ret_wo.getRl_prd_qty() >= ret_wo.getPln_prd_qty()) {
				gszMsgBuf = "内部订单 [" + ret_wo.getWo_id() + "] 没有足够的数量!";
				return new SimpleRtnBeen(E_XPUNPACK_INVALID_WO_COUNT);
			}
			if(ret_wo.getCus_id_fk() == null){
				gszMsgBuf = "内部订单 [" + ret_wo.getWo_id() + "]的客户代码为null!";
				return new SimpleRtnBeen(E_XPUNPACK_INVALID_CUS_ID);
			}
		}

		return new SimpleRtnBeen(ret_wo);
	}

	/**
	 * Get current wo's mdl info
	 * 
	 * @param ret_wo
	 * @return
	 */
	private SimpleRtnBeen bisMdlDefCheck(Ret_wo ret_wo) {
		Bis_mdl_def bis_mdl_def = new Bis_mdl_def();
		// Check wo mdl
		bis_mdl_def = bisMdlDefDao.get(ret_wo.getMdl_id_fk());
		if (null == bis_mdl_def) {
			gszMsgBuf = " Not found record [" + ret_wo.getMdl_id_fk()
					+ "] in ["
					+ Bis_mdl_def.class.getSimpleName().toUpperCase() + "]!";
			return new SimpleRtnBeen(E_BIS_MDL_DEF + E_READ_NOT_FOUND);
		}
		return new SimpleRtnBeen(bis_mdl_def);
	}

	/**
	 * Check box info
	 * 
	 * @return
	 */
	private SimpleRtnBeen retBoxCheck(String boxId) {
		Ret_box ret_box = new Ret_box();
		ret_box = retBoxDao.getWithLock(boxId, LockMode.UPGRADE);
		if (null == ret_box) {
			gszMsgBuf = "箱子 [" + boxId + "] 不存在!";
			return new SimpleRtnBeen(E_RET_BOX + E_READ_NOT_FOUND);
		}

		if (!PROC_EMPTY.equals(ret_box.getBox_stat())) {
			gszMsgBuf = "箱子 [" + ret_box.getBox_id() + "] " + "状态是 ["
					+ ret_box.getBox_stat() + "], " + "必须是 " + PROC_EMPTY + "!";
			return new SimpleRtnBeen(E_XPUNPACK_INVALID_BOX_STATUS);
		}

		if (_YES.equals(ret_box.getReal_emp())) {
			if (0 != ret_box.getPrd_qty()) {
				gszMsgBuf = "Box [" + ret_box.getBox_id()
						+ "] is real empt, prd count is ["
						+ ret_box.getPrd_qty() + "], must be 0!";
				return new SimpleRtnBeen(E_XPUNPACK_BOX_CNT_INVALIED);
			}
		} else if (!_NO.equals(ret_box.getReal_emp())) {
			gszMsgBuf = "Box [" + ret_box.getBox_id() + "]'s real empt flg  ["
					+ ret_box.getReal_emp() + "] invalied!";
			return new SimpleRtnBeen(E_XPUNPACK_REAL_EMPT_FLG_INVALIED);
		}

		if (!_YES.equals(ret_box.getValid_flg())) {
			gszMsgBuf = "Box [" + ret_box.getBox_id() + "] is invalied!";
			return new SimpleRtnBeen(E_XPUNPACK_BOX_INVALIED);
		}
		if (ret_box.getPrd_qty().intValue() >= ret_box.getStd_qty().intValue()) {
			gszMsgBuf = "Box [" + ret_box.getBox_id() + "] is full!";
			return new SimpleRtnBeen(E_XPUNPACK_BOX_IS_FULL);
		}

		return new SimpleRtnBeen(ret_box);
	}

	/**
	 * Check mtrl box info
	 * 
	 * @param ret_wo
	 * @param boxId
	 * @return
	 */
	private SimpleRtnBeen retMtrlBoxCheck(String woId, String boxId) {
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		Ret_prd_in ret_prd_in = new Ret_prd_in();
		Ret_prd_inId ret_prd_inId = new Ret_prd_inId();

		String cus_id = retPrdInDao.getCusIdOfMtrlBox(woId, boxId);
		ret_prd_inId.setCus_id(cus_id);
		ret_prd_inId.setMtrl_box_id(boxId);

		ret_prd_in = retPrdInDao.getWithLock(ret_prd_inId, LockMode.UPGRADE);
		if (null == ret_prd_in) {
			gszMsgBuf = " 箱子[" + boxId + "]在内部订单[" + woId + "] 中不存在！！ ["
					+ Ret_prd_in.class.getSimpleName().toUpperCase() + "]!";
			return new SimpleRtnBeen(E_RET_PRD_IN + E_READ_NOT_FOUND);
		}
		rtnBeen.setObj(ret_prd_in);

		if (PROC_WAIT.equals(ret_prd_in.getPpbox_stat())) {
			gszMsgBuf = "来料箱[" + ret_prd_in.getId().getMtrl_box_id()
					+ "]尚未领料， 请先进行领料操作！";
			return new SimpleRtnBeen(E_XPUNPACK_MTRL_BOX_INVALIED);
		}

		if (PROC_EMPTY.equals(ret_prd_in.getPpbox_stat())) {
			gszMsgBuf = "来料箱[" + ret_prd_in.getId().getMtrl_box_id()
					+ "]已经释放完毕！";
			return new SimpleRtnBeen(E_XPUNPACK_MTRL_BOX_ALREADY_EMPT);
		}

		if (0 >= ret_prd_in.getPrd_act_qty()) {
			gszMsgBuf = "Mtrl box[" + ret_prd_in.getId().getMtrl_box_id()
					+ "] is not panel to use.";
			return new SimpleRtnBeen(E_XPUNPACK_PRD_IN_NOT_ENOUGH);
		}

		return rtnBeen;
	}

	/**
	 * Check prd info
	 * 
	 * @return
	 */
	private SimpleRtnBeen retPrdInfoCheck(String prdId,String cusId) {
		Ret_prd_info ret_prd_info = new Ret_prd_info();
		ret_prd_info = retPrdInfoDao.get(prdId);
		if (null != ret_prd_info) {
			if(ret_prd_info.getWo_id_fk().equals(inTrx.getWo_id())){
				gszMsgBuf = "玻璃重复[" + prdId + "]!";
				return new SimpleRtnBeen(E_XPUNPACK_PRD_INFO_EXIST);
			}
			
			/**
			 * 1、已投产品内部订单无信息时，可以继续投产；
			 * 2、已投产品内部订单有信息时，已投产品的客户订单已维护SGID，并且预投产品客户订单也维护了SGID，则不允许投产
			 * 其他情况允许投产
			 */
			Ret_wo ret_wo = retWoDao.getWithLock(ret_prd_info.getWo_id_fk(), LockMode.UPGRADE);
			if (ret_wo != null) {
				List<Bis_data> dataList = new ArrayList<Bis_data>();
				String hql = "FROM Bis_data where data_cate = 'SGID' and ext_1 = '" + ret_wo.getCus_id_fk() + "'" ;	
				dataList = bisDataDao.find(hql);
				if(!dataList.isEmpty()){
					hql = "FROM Bis_data where data_cate = 'SGID' and ext_1 = '" + cusId + "'" ;
					dataList = bisDataDao.find(hql);
					if(!dataList.isEmpty()){
						gszMsgBuf = "玻璃重复[" + prdId + "]!";
						return new SimpleRtnBeen(E_XPUNPACK_PRD_INFO_EXIST);
					}
				}
			} 
			
			prdId = buildPrdIdByWo(prdId,inTrx.getWo_id());
			ret_prd_info = retPrdInfoDao.get(prdId+"");
			if(null != ret_prd_info){
				gszMsgBuf = "玻璃重复[" + prdId + "]!";
				return new SimpleRtnBeen(E_XPUNPACK_PRD_INFO_EXIST);
			}
			return new SimpleRtnBeen(RETURN_SHT_ID_BY_WO,new String(prdId),"根据工单ID组合生成");
		}

		return new SimpleRtnBeen(_NORMAL,prdId+"_"+inTrx.getWo_id());
	}
	private String buildPrdIdByWo(String prdId,String woId){
		return prdId + "_" + woId;
	}

	/**
	 * Check prd indt
	 * 
	 * @return
	 */
	private SimpleRtnBeen retPrdIndtCheck(String prdId) {
		Ret_prd_indt ret_prd_indt = new Ret_prd_indt();
		Ret_prd_indtId ret_prd_indtId = new Ret_prd_indtId();
		ret_prd_indtId.setVdr_prd_seq_id(prdId);
		ret_prd_indtId.setAct_typ(_NO);
		ret_prd_indt = retPrdIndtDao.get(ret_prd_indtId);
		if (null != ret_prd_indt) {
			gszMsgBuf = "[" + prdId + "] exist in ["
					+ Ret_prd_indt.class.getSimpleName().toUpperCase() + "]!";
			return new SimpleRtnBeen(E_XPUNPACK_PRD_INFO_EXIST);
		}

		return new SimpleRtnBeen(ret_prd_indt);
	}

	/**
	 * Get current path ope info
	 * 
	 * @param ret_wo
	 * @return SimpleRtnBeen(RouteObj)
	 */
	private SimpleRtnBeen getPathInfoByWo(Ret_wo ret_wo, Bis_mdl_def bis_mdl_def) {
		Bis_path bis_path = new Bis_path();
		Bis_pathId bis_pathId = new Bis_pathId();
		Bis_ope bis_ope = new Bis_ope();
		Bis_opeId bis_opeId = new Bis_opeId();
		RouteObj routeObj = new RouteObj();

		bis_pathId.setPath_id_fk(ret_wo.getPath_id_fk());
		bis_pathId.setPath_ver_fk(ret_wo.getPath_ver_fk());
		bis_pathId.setCr_ope_no(ret_wo.getStr_ope_no());
		bis_path = bisPathDao.get(bis_pathId);
		if (null == bis_path) {
			gszMsgBuf = " 找不到记录 [" + bis_pathId.toString() + "] in ["
					+ Bis_path.class.getSimpleName().toUpperCase() + "]!";
			return new SimpleRtnBeen(E_BIS_PATH + E_READ_NOT_FOUND);
		}

		bis_opeId.setOpe_id(bis_path.getCr_ope_id_fk());
		bis_opeId.setOpe_ver(bis_path.getCr_ope_ver_fk());
		bis_ope = bisOpeDao.get(bis_opeId);
		if (null == bis_ope) {
			gszMsgBuf = " 找不到记录 [" + bis_opeId.toString() + "] in ["
					+ Bis_ope.class.getSimpleName().toUpperCase() + "]!";
			return new SimpleRtnBeen(E_BIS_PATH + E_READ_NOT_FOUND);
		}

		routeObj.setPath(bis_path);
		routeObj.setOpe(bis_ope);
		routeObj.setLRc(_NORMAL);

		return new SimpleRtnBeen(routeObj);
	}

	/**
	 * Get next path info
	 * 
	 * @param bis_path
	 * @param bis_ope
	 * @return
	 */
	private SimpleRtnBeen getNextPathInfo(Bis_path bis_path, Bis_ope bis_ope) {
		RouteObj routeObjRtn = new RouteObj();
		routeObjRtn = bisPathDao.getNxPath(bis_path);
		return new SimpleRtnBeen(routeObjRtn.getLRc(), routeObjRtn);
	}

	/**
	 * Add prd_indt
	 * 
	 * @return RouteObj
	 */
	private SimpleRtnBeen addPrdIndtForUnpack(Ret_prd_in ret_prd_in, String prd_seq_id,
			Ret_cus_prd_indt ret_cus_prd_indt) {
		int slot_no_box = retBoxDao.get(inTrx.getBox_id()).getStd_qty();
		Ret_prd_indt ret_prd_indt = new Ret_prd_indt();
		Ret_prd_indtId ret_prd_indtId = new Ret_prd_indtId();

		ret_prd_indtId.setVdr_prd_seq_id(prd_seq_id);
		ret_prd_indtId.setAct_typ(_NO);
		ret_prd_indt.setId(ret_prd_indtId);

		ret_prd_indt.setPrd_stat(PROC_RELS);
		ret_prd_indt.setMtrl_box_id_fk(ret_prd_in.getId().getMtrl_box_id());
		/**
		 * ret_cus_prd_indt 为null，代表非客户，slot_no需按规则生成；
		 * 非null时，代表为客户订单，slot_no按照ret_cus_prd_indt中的mtrl_slot_no获取
		 */
//		if(ret_cus_prd_indt != null){
//			ret_prd_indt.setMtrl_slot_no(ret_cus_prd_indt.getMtrl_slot_no());
//		}else{
			if (Util.isSpaceCheck(inTrx.getSlot_no())) {
		/*		String sql = "SELECT MAX(CAST(SLOT_NO AS SIGNED)) FROM Ret_prd_info WHERE box_id_fk='"+inTrx.getBox_id()+"'";
				List list = retPrdInfoDao.findBySQL(sql);
				String max_slot = list.get(0) == null ? 1+"" : ((BigInteger)list.get(0)).intValue()+1+""; */
	/*			String hql = "FROM Ret_prd_info WHERE　box_id_fk=?";
				list = retPrdInfoDao.list(hql, inTrx.getBox_id());*/
				String sql = "SELECT SLOT_NO FROM Ret_prd_info WHERE box_id_fk='"+inTrx.getBox_id()+"' ORDER BY  CAST(SLOT_NO AS SIGNED)";
				List list = retPrdInfoDao.findBySQL(sql);
				List<Integer> slots = new ArrayList<Integer>();
				for(int i = 0; i < list.size(); i++){
				     slots.add(Integer.parseInt((String)list.get(i)));
				}
				int tempSlot = 0;
				for(int i = 1; ; i++){
					if(!slots.contains(i)){
						tempSlot = i;
						break;
					}
				}
				if(tempSlot>slot_no_box){
					gszMsgBuf = "箱子["+ inTrx.getBox_id() + "]已满";
					return new SimpleRtnBeen(E_XPUNPACK_SLOT_NO_IN_MTRL_EXIST);
				}
				ret_prd_indt.setMtrl_slot_no(tempSlot+"");
			} else {
				int slot_no_inTx = Integer.valueOf(inTrx.getSlot_no());
				if (retPrdInfoDao.hasUserInputSlotInBox(inTrx.getBox_id(),
						inTrx.getSlot_no())) {
					gszMsgBuf = "子格位[" + inTrx.getSlot_no() + "]在箱子["
							+ inTrx.getBox_id() + "]中已经存在！";
					return new SimpleRtnBeen(E_XPUNPACK_SLOT_NO_IN_MTRL_EXIST);
				} else if (slot_no_inTx > slot_no_box) {
					gszMsgBuf = "输入的子格位为[" + inTrx.getSlot_no() + "]，而箱子[" 
							+ inTrx.getBox_id() + "]产品最大子格位为["
							+ slot_no_box + "]！";
					return new SimpleRtnBeen(E_XPUNPACK_SLOT_NO_IN_MTRL_EXIST);
				} else {
					ret_prd_indt.setMtrl_slot_no(inTrx.getSlot_no());
				}
//				else if (slot_no_inTx > slot_no_prdIn) {
//					gszMsgBuf = "输入的子格位为[" + inTrx.getSlot_no() + "]，而来料箱["
//							+ ret_prd_in.getId().getMtrl_box_id() + "]产品最大子格位为["
//							+ ret_prd_in.getBox_std_qty() + "]！";
//					return new SimpleRtnBeen(E_XPUNPACK_SLOT_NO_IN_MTRL_EXIST);
//				} 
		
			}
//		}
		ret_prd_indt.setWo_id_fk(inTrx.getWo_id());
		ret_prd_indt.setEvt_timestamp(gEvtTimestamp);
		ret_prd_indt.setEvt_usr(inTrx.getEvt_usr());
		retPrdIndtDao.save(ret_prd_indt);

		return new SimpleRtnBeen(ret_prd_indt);
	}

	/**
	 * Add new prd_info record
	 * 
	 * @param ret_box
	 * @param ret_wo
	 * @param bis_mdl_def
	 * @param bis_path
	 * @param bis_ope
	 * @param nx_bis_path
	 * @param nx_bis_ope
	 * @param ret_prd_in
	 * @return SimpleRtnBeen
	 */
	private SimpleRtnBeen addPrdInfoForUnpack(Ret_box ret_box, Ret_wo ret_wo,
			Bis_mdl_def bis_mdl_def, Bis_path bis_path, Bis_ope bis_ope,
			Bis_path nx_bis_path, Bis_ope nx_bis_ope, Ret_prd_in ret_prd_in,
			String slotNo ,String prd_seq_id,String fab_sn, 
			Ret_cus_prd_in ret_cus_prd_in) {

		Integer pnl_std_pnl = 0;
		Ret_prd_info ret_prd_info = new Ret_prd_info();

		// Set ret_prd_info
		ret_prd_info.setPrd_seq_id(prd_seq_id);
		ret_prd_info.setPrd_stat(PROC_IN_PROCESS);
		ret_prd_info.setPrd_seq_typ(PRD_TYPE_SHEET);
		ret_prd_info.setBox_id_fk(inTrx.getBox_id());
		ret_prd_info.setSlot_no(slotNo);
		ret_prd_info.setMdl_typ_fk(bis_mdl_def.getMdl_typ());
		ret_prd_info.setMdl_cate_fk(ret_wo.getMdl_cate_fk());
		ret_prd_info.setMdl_id_fk(bis_mdl_def.getMdl_id());
		ret_prd_info.setMtrl_box_id_fk(inTrx.getMtrl_box_id());
		ret_prd_info.setMtrl_prod_id_fk(ret_prd_in.getMtrl_prod_id_fk());
		ret_prd_info.setLayot_id_fk(inTrx.getLayot_id());
		ret_prd_info.setX_axis_cnt_fk(Integer.valueOf(inTrx.getX_axis_cnt()));
		ret_prd_info.setY_axis_cnt_fk(Integer.valueOf(inTrx.getY_axis_cnt()));
		/**
		 * ret_cus_prd_in 为null，代表非客户；
		 * 非null时，代表为客户订单，group id按照ret_cus_prd_in中的cus_group_id
		 */
		if(ret_cus_prd_in != null){
			ret_prd_info.setGroup_id(ret_cus_prd_in.getCus_group_id());
		}else{
			ret_prd_info.setGroup_id("");
		}
		
		pnl_std_pnl = ret_prd_info.getX_axis_cnt_fk()
				* ret_prd_info.getY_axis_cnt_fk();
		ret_prd_info.setPrd_qty(pnl_std_pnl);
		ret_prd_info.setPrd_std_qty(pnl_std_pnl);
		if (!Util.isSpaceCheck(inTrx.getThickness())) {
			ret_prd_info.setPrd_thickness(Double.valueOf(inTrx.getThickness()));
		} else {
			ret_prd_info.setPrd_thickness(0.0);
		}
		ret_prd_info.setPv_prd_thickness(0.0);

		ret_prd_info.setPrty(ret_wo.getWo_prty());
		

		Ret_tm_cus_prd_indt retTmCusPrdIndt = retTmCusPrdIndtDao.get(prd_seq_id);
		if(retTmCusPrdIndt!=null){
			ret_prd_info.setPrd_grade(retTmCusPrdIndt.getProductgrade());
			ret_prd_info.setExt_2(retTmCusPrdIndt.getProductgrade());
		}else{
			ret_prd_info.setPrd_grade(_OK);
		}
		
		ret_prd_info.setPv_prd_grade(_OK);
		// 特定站点过账标识[DATA-PRST-EXT2]
		ret_prd_info.setCus_sn(_NO1_50);
		ret_prd_info.setProc_flg("Y");

		// Path info
		ret_prd_info.setCr_path_id_fk(bis_path.getId().getPath_id_fk());
		ret_prd_info.setCr_path_ver_fk(bis_path.getId().getPath_ver_fk());
		ret_prd_info.setCr_ope_no_fk(bis_path.getId().getCr_ope_no());
		ret_prd_info.setCr_ope_id_fk(bis_path.getCr_ope_id_fk());
		ret_prd_info.setCr_ope_ver_fk(bis_path.getCr_ope_ver_fk());

		ret_prd_info.setCr_proc_id_fk(bis_ope.getProc_id());
		ret_prd_info.setCr_toolg_id_fk(bis_ope.getToolg_id());
		ret_prd_info.setCr_tool_id_fk(inTrx.getTool_id());
		ret_prd_info.setTool_id_fk(inTrx.getTool_id());
		if(last_ope == PATH_IS_FINISH){
			ret_prd_info.setNx_path_id_fk(bis_path.getId().getPath_id_fk());
			ret_prd_info.setNx_path_ver_fk(bis_path.getId().getPath_ver_fk());
			ret_prd_info.setNx_ope_no_fk(_SPACE);
			ret_prd_info.setNx_ope_id_fk(_SPACE);
			ret_prd_info.setNx_ope_ver_fk(_SPACE);
			ret_prd_info.setNx_proc_id_fk(_SPACE);
			ret_prd_info.setNx_toolg_id_fk(_SPACE);
		}else{
			ret_prd_info.setNx_path_id_fk(nx_bis_path.getId().getPath_id_fk());
			ret_prd_info.setNx_path_ver_fk(nx_bis_path.getId().getPath_ver_fk());
			ret_prd_info.setNx_ope_no_fk(nx_bis_path.getId().getCr_ope_no());
			ret_prd_info.setNx_ope_id_fk(nx_bis_ope.getId().getOpe_id());
			ret_prd_info.setNx_ope_ver_fk(nx_bis_ope.getId().getOpe_ver());
			ret_prd_info.setNx_proc_id_fk(nx_bis_ope.getProc_id());
			ret_prd_info.setNx_toolg_id_fk(nx_bis_ope.getToolg_id());
		}

		// Time info
		ret_prd_info.setAct_stb_timestamp(gEvtTimestamp);
		ret_prd_info.setFst_logon_timestamp(gEvtTimestamp);

		// rubbing_time
		ret_prd_info.setT_rubbing_time(0);
		ret_prd_info.setC_rubbing_time(0);

		// Event info
		ret_prd_info.setEvt_dept("");
		ret_prd_info.setEvt_cate(EVT_STB_INPR);
		ret_prd_info.setEvt_usr(inTrx.getEvt_usr());
		ret_prd_info.setEvt_timestamp(gEvtTimestamp);
		ret_prd_info.setEvt_time_d(gEvtTimeD);
		ret_prd_info.setEvt_seq_id(gEvtSeqID);

		ret_prd_info.setWo_id_fk(inTrx.getWo_id());
		ret_prd_info.setSo_id_fk(ret_wo.getSo_id());

		ret_prd_info.setDest_shop(ret_wo.getDest_shop());
		ret_prd_info.setQrs_ovr_flg(_NO);
		ret_prd_info.setBnk_flg(BANK_OUT);
		ret_prd_info.setPrd_admin_flg("NNNNNNNNNNNNNNNNNNNN");
		ret_prd_info.setFab_sn(fab_sn);//NO.01
		logger.info("set fab sn:" + fab_sn);
		retPrdInfoDao.save(ret_prd_info);
		if (ret_box.getBnk_flg().equals(WIP_REATIN)) {// 在制保留的箱子，转进来的产品均将其BNK_FLG置为3
			gEvtTimestamp = Util.getCurrentTimestamp();
			gEvtTimeD = Util.getDoubleTime();
			gEvtSeqID = GUIDGenerator.javaGUID();
			ret_prd_info.setEvt_timestamp(gEvtTimestamp);
			ret_prd_info.setEvt_time_d(gEvtTimeD);
			ret_prd_info.setEvt_seq_id(gEvtSeqID);
			ret_prd_info.setEvt_cate(EVT_WIP_RETAIN);
			ret_prd_info.setBnk_flg(WIP_REATIN);
			retPrdInfoDao.update(ret_prd_info);
		}
		return new SimpleRtnBeen(ret_prd_info);
	}

	/**
	 * Check sht in cur box
	 * 
	 * @return
	 */
	private SimpleRtnBeen checkRetPrdInfoMix(Ret_prd_info newPrdInfo,
			Ret_box ret_box, Ret_wo ret_wo) {
		List<Ret_prd_info> ret_prd_infoList = new ArrayList<Ret_prd_info>();
		Ret_prd_info last_prd = new Ret_prd_info();

		String sql = "From Ret_prd_info where box_id_fk = '"
				+ ret_box.getBox_id() + "' and prd_seq_id <>'"
				+ newPrdInfo.getPrd_seq_id() + "'";
		ret_prd_infoList = retPrdInfoDao.find(sql, 0, 1);
		if (!ret_prd_infoList.isEmpty()) {
			last_prd = ret_prd_infoList.get(0);

			// Proc info
			if (!newPrdInfo.getNx_proc_id_fk().equals(
					last_prd.getNx_proc_id_fk())) {
				gszMsgBuf = "玻璃的下一制程不能混！ [" + newPrdInfo.getPrd_seq_id() + "]["
						+ newPrdInfo.getNx_proc_id_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getNx_proc_id_fk() + "] ";
				return new SimpleRtnBeen(SHT_NX_PROC_ID_MIX);
			}
			if (!newPrdInfo.getCr_proc_id_fk().equals(
					last_prd.getCr_proc_id_fk())) {
				gszMsgBuf = "玻璃的当前制程不能混！[" + newPrdInfo.getPrd_seq_id() + "]["
						+ newPrdInfo.getCr_proc_id_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getCr_proc_id_fk() + "] ";
				return new SimpleRtnBeen(SHT_CR_PROC_ID_MIX);
			}

			// MDL info
			if (!newPrdInfo.getMdl_cate_fk().equals(last_prd.getMdl_cate_fk())) {
				gszMsgBuf = "玻璃的产品类型不能混！ [" + newPrdInfo.getPrd_seq_id() + "]["
						+ newPrdInfo.getMdl_cate_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getMdl_cate_fk() + "] ";
				return new SimpleRtnBeen(SHT_MDL_CATE_MIX);
			}
			if (!newPrdInfo.getMdl_id_fk().equals(last_prd.getMdl_id_fk())) {
				gszMsgBuf = "玻璃的产品名称不能混！[" + newPrdInfo.getPrd_seq_id() + "]["
						+ newPrdInfo.getMdl_id_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getMdl_id_fk() + "] ";
				return new SimpleRtnBeen(SHT_MDL_ID_MIX);
			}
			if (!newPrdInfo.getMdl_typ_fk().equals(last_prd.getMdl_typ_fk())) {
				gszMsgBuf = "玻璃的产品尺寸不能混！ [" + newPrdInfo.getPrd_seq_id() + "]["
						+ newPrdInfo.getMdl_typ_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getMdl_typ_fk() + "] ";
				return new SimpleRtnBeen(SHT_MDL_TYPE_MIX);
			}

			// Path in
			if (!newPrdInfo.getNx_path_id_fk().equals(
					last_prd.getNx_path_id_fk())) {
				gszMsgBuf = "玻璃的下一工艺路线不能混！[" + newPrdInfo.getPrd_seq_id()
						+ "][" + newPrdInfo.getNx_path_id_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getNx_path_id_fk() + "] ";
				return new SimpleRtnBeen(SHT_PATH_ID_MIX);
			}
			if (!newPrdInfo.getNx_path_ver_fk().equals(
					last_prd.getNx_path_ver_fk())) {
				gszMsgBuf = "玻璃的下一工艺路线版本不能混！ [" + newPrdInfo.getPrd_seq_id()
						+ "][" + newPrdInfo.getNx_path_ver_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getNx_path_ver_fk() + "] ";
				return new SimpleRtnBeen(SHT_PATH_VER_MIX);
			}
			if (!newPrdInfo.getNx_ope_id_fk()
					.equals(last_prd.getNx_ope_id_fk())) {
				gszMsgBuf = "玻璃的下一站点ID不能混！ [" + newPrdInfo.getPrd_seq_id()
						+ "][" + newPrdInfo.getNx_ope_id_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getNx_ope_id_fk() + "] ";
				return new SimpleRtnBeen(SHT_OPE_ID_MIX);
			}
			if (!newPrdInfo.getNx_ope_no_fk()
					.equals(last_prd.getNx_ope_no_fk())) {
				gszMsgBuf = "玻璃的下一站点编号不能混！ [" + newPrdInfo.getPrd_seq_id()
						+ "][" + newPrdInfo.getNx_ope_no_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getNx_ope_no_fk() + "] ";
				return new SimpleRtnBeen(SHT_OPE_NO_MIX);
			}
			if (!newPrdInfo.getNx_ope_ver_fk().equals(
					last_prd.getNx_ope_ver_fk())) {
				gszMsgBuf = "玻璃的下一站点版本不能混！[" + newPrdInfo.getPrd_seq_id()
						+ "][" + newPrdInfo.getNx_ope_ver_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getNx_ope_ver_fk() + "] ";
				return new SimpleRtnBeen(SHT_OPE_VER_MIX);
			}

			// Tool info
			if (!newPrdInfo.getNx_toolg_id_fk().equals(
					last_prd.getNx_toolg_id_fk())) {
				gszMsgBuf = "玻璃的设备组不能混！[" + newPrdInfo.getPrd_seq_id() + "]["
						+ newPrdInfo.getNx_toolg_id_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getNx_toolg_id_fk() + "] ";
				return new SimpleRtnBeen(SHT_NX_TOOLG_MIX);
			}

			// WO info
			if (!newPrdInfo.getWo_id_fk().equals(last_prd.getWo_id_fk())) {
				gszMsgBuf = "玻璃的内部订单不能混！ [" + newPrdInfo.getPrd_seq_id() + "]["
						+ newPrdInfo.getWo_id_fk() + "] vs ["
						+ last_prd.getPrd_seq_id() + "]["
						+ last_prd.getWo_id_fk() + "] ";
				return new SimpleRtnBeen(SHT_WO_ID_MIX);
			}
			
			//GROUP ID,针对客户来料的订单，不同group id(值来自RET_CUS_PRD_IN的CUS_GROUP_ID,即owner id)的产品不能混装
//			if(_YES.equals(ret_wo.getSwh_cnt_flg())||"007".equals(ret_wo.getCus_id_fk())){//客户来料标记
//				if(!newPrdInfo.getGroup_id().equals(last_prd.getGroup_id())){
//					gszMsgBuf = "玻璃的组代码不能混！[" + newPrdInfo.getPrd_seq_id()+ "]["
//						+ newPrdInfo.getGroup_id() + "] vs ["
//						+ last_prd.getPrd_seq_id() + "]["
//						+ last_prd.getGroup_id() + "]";
//					return new SimpleRtnBeen(GROUP_ID_MIX);
//				}
//				if(!newPrdInfo.getPrd_grade().equals(last_prd.getPrd_grade())){
//					gszMsgBuf = "玻璃的等级不能混！[" + newPrdInfo.getPrd_seq_id()+ "]["
//						+ newPrdInfo.getPrd_grade() + "] vs ["
//						+ last_prd.getPrd_seq_id() + "]["
//						+ last_prd.getPrd_grade() + "]";
//					return new SimpleRtnBeen(GROUP_ID_MIX);
//				}
//			}
		}

		return new SimpleRtnBeen(_NORMAL);
	}

	/**
	 * Update ret_box info
	 * 
	 * @param ret_box
	 * @param ret_wo
	 * @param bis_mdl_def
	 * @return
	 */
	private SimpleRtnBeen updateBoxInfo(Ret_box ret_box, Ret_wo ret_wo,
			Bis_mdl_def bis_mdl_def,
			Ret_cus_prd_in ret_cus_prd_in) {
		if (EMPTY_CARRIER.equals(ret_box.getReal_emp())) {
			ret_box.setReal_emp(EXIST_CARRIER);
			ret_box.setPrd_qty(1);

			ret_box.setMdl_id_fk(bis_mdl_def.getMdl_id());
			ret_box.setMdl_typ_fk(bis_mdl_def.getMdl_typ());
			ret_box.setMdl_cate_fk(ret_wo.getMdl_cate_fk());
			ret_box.setWo_id_fk(ret_wo.getWo_id());
			ret_box.setPrty(ret_wo.getWo_prty());
			/**
			 * ret_cus_prd_in 为null，代表非客户；
			 * 非null时，代表为客户订单，group id按照ret_cus_prd_in中的cus_group_id
			 */
			if(ret_cus_prd_in != null){
				ret_box.setGroup_id(ret_cus_prd_in.getCus_group_id());
			}else{
				ret_box.setGroup_id("");
			}
		} else {
			ret_box.setPrd_qty(ret_box.getPrd_qty() + 1);
		}

		retBoxDao.update(ret_box);
		return new SimpleRtnBeen(ret_box);
	}

	/**
	 * Update mtrl box/ret_prd_in info
	 * 
	 * @param ret_prd_in
	 * @return Ret_prd_in
	 */
	private SimpleRtnBeen updateMtrlBoxInfo(Ret_prd_in ret_prd_in) {
		if (PROC_WFRL.equals(ret_prd_in.getPpbox_stat())) {
			ret_prd_in.setEvt_cate(EVT_STB_INPR);
			ret_prd_in.setPrd_proc_qty(1);
			ret_prd_in.setPrd_act_qty(ret_prd_in.getPrd_tl_qty() - 1);
			if (0 == ret_prd_in.getPrd_act_qty()) {//fix bug：来料箱只有一个产品ID时，来料箱状态不会变为EMPT
				ret_prd_in.setPpbox_stat(PROC_EMPTY);
			}else{
				ret_prd_in.setPpbox_stat(PROC_RELS);
			}
		} else if (PROC_RELS.equals(ret_prd_in.getPpbox_stat())) {
			ret_prd_in.setPrd_proc_qty(ret_prd_in.getPrd_proc_qty() + 1);
			ret_prd_in.setPrd_act_qty(ret_prd_in.getPrd_act_qty() - 1);
			if (0 == ret_prd_in.getPrd_act_qty()) {
				ret_prd_in.setPpbox_stat(PROC_EMPTY);
			}
		} else {
			gszMsgBuf = "Mtrl box's status [" + ret_prd_in.getPpbox_stat()
					+ "] is invalied!";
			return new SimpleRtnBeen(E_XPUNPACK_MTRL_BOX_INVALIED);
		}

		retPrdInDao.update(ret_prd_in);
		return new SimpleRtnBeen(ret_prd_in);
	}

	/**
	 * Update wo info
	 * 
	 * @param ret_wo
	 * @return Ret_wo
	 */
	private SimpleRtnBeen updateWoInfo(Ret_wo ret_wo) {
		if (0 == ret_wo.getRl_prd_qty()) {
			ret_wo.setAct_stb_timestamp(gEvtTimestamp);
		}
		if (null == ret_wo.getAct_stb_timestamp()){
			ret_wo.setAct_stb_timestamp(gEvtTimestamp);
		}
		ret_wo.setRl_prd_qty(ret_wo.getRl_prd_qty() + 1);
		retWoDao.update(ret_wo);
		return new SimpleRtnBeen(ret_wo);
	}

	private void setOutTrx(Ret_prd_indt ret_prd_indt,
			Ret_prd_info ret_prd_info, Ret_box ret_box ,
			Ret_wo ret_wo , Ret_prd_in ret_prd_in) {
		outTrx.setMtrl_box_id_fk(ret_prd_indt.getMtrl_box_id_fk());
		outTrx.setSlot_no(ret_prd_info.getSlot_no());
		outTrx.setPrd_seq_id(ret_prd_info.getPrd_seq_id());
		outTrx.setBox_id_fk(ret_prd_info.getBox_id_fk());
		outTrx.setBox_prd_qty(ret_box.getPrd_qty());
		outTrx.setEvt_timestamp(gEvtTimestamp.toString());
		outTrx.setEvt_usr(inTrx.getEvt_usr());
		outTrx.setLayot_id_fk(ret_prd_info.getLayot_id_fk());
		outTrx.setX_axis_cnt_fk(String.valueOf(ret_prd_info.getX_axis_cnt_fk()));
		outTrx.setY_axis_cnt_fk(String.valueOf(ret_prd_info.getY_axis_cnt_fk()));
		outTrx.setFrom_thickness(ret_wo.getFrom_thickness());
		outTrx.setTo_thickness(ret_wo.getTo_thickness());
		outTrx.setPln_prd_qty(ret_wo.getPln_prd_qty());
		outTrx.setRl_prd_qty(ret_wo.getRl_prd_qty());
		outTrx.setRet_prd_in(ret_prd_in);
		outTrx.setPrd_admin_flg(ret_prd_info.getPrd_admin_flg());
		outTrx.setMdl_id_fk(ret_prd_info.getMdl_id_fk());
		outTrx.setCr_tool_id_fk(ret_prd_info.getCr_tool_id_fk());
		outTrx.setCr_path_id_fk(ret_prd_info.getCr_path_id_fk());
		outTrx.setCr_path_ver_fk(ret_prd_info.getCr_path_ver_fk());
		outTrx.setCr_ope_no_fk(ret_prd_info.getCr_ope_no_fk());
		outTrx.setCr_ope_id_fk(ret_prd_info.getCr_ope_id_fk());
		outTrx.setCr_ope_ver_fk(ret_prd_info.getCr_ope_ver_fk());
		outTrx.setCr_proc_id_fk(ret_prd_info.getCr_proc_id_fk());
		outTrx.setWo_id_fk(ret_prd_info.getWo_id_fk());		
		outTrx.setFab_sn(ret_prd_info.getFab_sn());
		outTrx.setGroup_id(ret_prd_info.getGroup_id());
		outTrx.setCus_id(ret_wo.getCus_id_fk());
	}

	/**
	 * Cancel unpack, update relevant data
	 * 
	 * @return
	 */
	private long cancelUnpackOpe() {
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		Ret_prd_info ret_prd_info = new Ret_prd_info();
		Ret_prd_in ret_prd_in = new Ret_prd_in();
		Ret_wo ret_wo = new Ret_wo();
		
		// Get & check prd_info
		rtnBeen = checkPrdInfoForCancelUnpack(inTrx.getPrd_seq_id());
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_prd_info = (Ret_prd_info) rtnBeen.getObj();
		}

		rtnBeen = ResetPrdLotInfoForCancelUnpack(inTrx.getPrd_seq_id());
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_prd_info = (Ret_prd_info) rtnBeen.getObj();
		}
		// Reset ret_prd_in
		rtnBeen = resetRetPrdInForCancelUnpack(ret_prd_info.getWo_id_fk(),
				ret_prd_info.getMtrl_box_id_fk());
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_prd_in = (Ret_prd_in) rtnBeen.getObj();
		}

		// Delete ret_prd_indt
		rtnBeen = delRetPrdIndtForCancelUnpack(ret_prd_info.getPrd_seq_id());
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		}

		// Reset ret_box
		rtnBeen = resetRetBoxForCancelUnpack(ret_prd_info.getBox_id_fk(),
				ret_prd_in);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		}

		// Delete ret_prd_info
		rtnBeen = delRetPrdInfoForCancelUnpack(ret_prd_info);
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		}

		// Delete ret_grd_info
		rtnBeen = delRetGrdInfoForCancelUnpack();
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		}
		
		// Reset ret_wo
		rtnBeen = resetRetWoForCancelUnpack(ret_prd_info.getWo_id_fk());
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		} else {
			ret_wo = (Ret_wo) rtnBeen.getObj();
		}

		// Delete defect info
		rtnBeen = delDefForCancelUnpack(ret_prd_info.getPrd_seq_id());
		if (rtnBeen.getlRc() != _NORMAL) {
			return rtnBeen.getlRc();
		}

		// Set outTrx
		setOutTrxForCancelUnpack(inTrx.getPrd_seq_id(), ret_wo ,ret_prd_in);
	
		return _NORMAL;
	}

	/**
	 * Get & check prd_info for cancel unpack
	 * 
	 * @param prd_seq_id
	 * @return {Ret_prd_info}
	 */
	private SimpleRtnBeen checkPrdInfoForCancelUnpack(String prd_seq_id) {
		Ret_prd_info ret_prd_info = new Ret_prd_info();

		ret_prd_info = retPrdInfoDao.get(prd_seq_id);
		if (null == ret_prd_info) {
			gszMsgBuf = new NotFoundRtnBeen(prd_seq_id, Ret_prd_info.class)
					.toString();
			return new SimpleRtnBeen(E_RET_PRD_INFO + E_READ_NOT_FOUND);
		}

		// Status
		if (!PROC_IN_PROCESS.equals(ret_prd_info.getPrd_stat())) {
			gszMsgBuf = "要删除的玻璃状态必须是[" + PROC_IN_PROCESS + "]，当前玻璃["
					+ prd_seq_id + "]状态为[" + ret_prd_info.getPrd_stat()
					+ "]，禁止取消！";
			return new SimpleRtnBeen(E_XPUNPACK_CANCEL_PRD_INFO_STATUS_INVALIED);
		}
		// lot_id
//		if (!Util.isSpaceCheck(ret_prd_info.getLot_id())) {
//			gszMsgBuf = "产品[" + ret_prd_info.getPrd_seq_id() + "]已绑定批次["
//					+ ret_prd_info.getLot_id() + "]，禁止取消！";
//			return new SimpleRtnBeen(E_XPUNPACK_CANCEL_PRD_INFO_STATUS_INVALIED);
//		}
		
		
		//取消释放功能,检查玻璃是不是在当前途程的首站点,如果不是则报错
 		String path_id = ret_prd_info.getCr_path_id_fk();
 		String path_ver = ret_prd_info.getCr_path_ver_fk();
 		
 		if (Util.isSpaceCheck(path_id) || Util.isSpaceCheck(path_ver)) {
 			gszMsgBuf = "当前玻璃[" + prd_seq_id + "]工艺线路为空";
			return new SimpleRtnBeen(
					E_XPUNPACK_CANCEL_PRD_INFO_CR_PROC_INVALIED);
		}
 		
 		Bis_pathiId bisPathiId = new Bis_pathiId();
 		Bis_pathi bisPathi = new Bis_pathi();
 		bisPathiId.setPath_id(path_id);
 		bisPathiId.setPath_ver(path_ver);
 		bisPathi = bisPathiDao.get(bisPathiId);
 		
 		if (bisPathi == null) {
 			gszMsgBuf = "当前玻璃[" + prd_seq_id + "]工艺线路不存在";
			return new SimpleRtnBeen(
					E_XPUNPACK_CANCEL_PRD_INFO_CR_PROC_INVALIED);
		}
 		
 		String first_ope_id = bisPathi.getFirst_ope_no();
 		
 		if (Util.isSpaceCheck(first_ope_id)) {
 			gszMsgBuf = "当前玻璃[" + prd_seq_id + "]工艺线路bis_pathi中维护有误";
			return new SimpleRtnBeen(
					E_XPUNPACK_CANCEL_PRD_INFO_CR_PROC_INVALIED);
		}
 		
 		if (!(first_ope_id).equals(ret_prd_info.getCr_ope_no_fk())) {
 			gszMsgBuf = "要删除的玻璃状态必须在["+first_ope_id+"]，当前玻璃[" + prd_seq_id + "]位于["
					+ ret_prd_info.getCr_ope_no_fk() + "]，禁止取消！";
			return new SimpleRtnBeen(
					E_XPUNPACK_CANCEL_PRD_INFO_CR_PROC_INVALIED);
		}
		return new SimpleRtnBeen(ret_prd_info);
	}

	/**
	 * Reset ret_prd_in
	 * 
	 * @param wo_id
	 * @param mtrl_box_id_fk
	 * @return {Ret_prd_in}
	 */
	private SimpleRtnBeen resetRetPrdInForCancelUnpack(String wo_id,
			String mtrl_box_id_fk) {
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		Ret_prd_in ret_prd_in = new Ret_prd_in();

		rtnBeen = retPrdInDao.getRetPrdInByWoAndBox(wo_id, mtrl_box_id_fk);
		if (E_RET_PRD_IN + E_READ_NOT_FOUND == rtnBeen.getlRc()) {
			gszMsgBuf = new NotFoundRtnBeen("boxId:[" + mtrl_box_id_fk
					+ "], WoId:[" + wo_id + "] ", Ret_prd_in.class).toString();
			return new SimpleRtnBeen(rtnBeen.getlRc());
		} else {
			ret_prd_in = (Ret_prd_in) rtnBeen.getObj();
		}

		// Status
		if (PROC_RELS.equals(ret_prd_in.getPpbox_stat())) {
			if (ret_prd_in.getPrd_proc_qty().equals(1)) {
				ret_prd_in.setPpbox_stat(PROC_WFRL);
			}
		} else if (PROC_EMPTY.equals(ret_prd_in.getPpbox_stat())) {
			ret_prd_in.setPpbox_stat(PROC_RELS);
		} else {
			gszMsgBuf = "Mtrl box's status [" + ret_prd_in.getPpbox_stat()
					+ "] is invalied! Must [" + PROC_RELS + "] or ["
					+ PROC_RELS + "]";
			return new SimpleRtnBeen(E_XPUNPACK_MTRL_BOX_INVALIED);
		}
		ret_prd_in.setPrd_proc_qty(ret_prd_in.getPrd_proc_qty() - 1);
		ret_prd_in.setPrd_act_qty(ret_prd_in.getPrd_act_qty() + 1);
		ret_prd_in.setEvt_cate(EVT_CANCEL_UNPACK);
		ret_prd_in.setEvt_usr(inTrx.getEvt_usr());
		retPrdInDao.update(ret_prd_in);

		return new SimpleRtnBeen(ret_prd_in);
	}

	/**
	 * Delete ret_prd_indt
	 * 
	 * @param prd_seq_id
	 * @return
	 */
	private SimpleRtnBeen delRetPrdIndtForCancelUnpack(String prd_seq_id) {
		Ret_prd_indtId ret_prd_indtId = new Ret_prd_indtId();

		ret_prd_indtId.setVdr_prd_seq_id(prd_seq_id);
		ret_prd_indtId.setAct_typ(_NO);
		retPrdIndtDao.deleteByKey(ret_prd_indtId);

		return new SimpleRtnBeen(_NORMAL);
	}

	/**
	 * Reset ret_box info
	 * 
	 * @param ret_box_id
	 * @param ret_prd_in
	 * @return {Ret_box}
	 */
	private SimpleRtnBeen resetRetBoxForCancelUnpack(String ret_box_id,
			Ret_prd_in ret_prd_in) {
		Ret_box ret_box = new Ret_box();
		ret_box = retBoxDao.getWithLock(ret_box_id, LockMode.UPGRADE);
		if (null == ret_box) {
			gszMsgBuf = new NotFoundRtnBeen(ret_box_id, Ret_box.class)
					.toString();
			return new SimpleRtnBeen(E_RET_BOX + E_READ_NOT_FOUND);
		}

		// Status
		if (!PROC_EMPTY.equals(ret_box.getBox_stat())) {
			gszMsgBuf = "Box [" + ret_box.getBox_id() + "] " + "status is ["
					+ ret_box.getBox_stat() + "], " + "must " + PROC_EMPTY
					+ "!";
			return new SimpleRtnBeen(E_XPUNPACK_INVALID_BOX_STATUS);
		}

		// Set Count
		if (ret_box.getPrd_qty().equals(1)) {
			ret_box = retBoxDao.setBoxEmpt(ret_box);
		} else {
			ret_box.setPrd_qty(ret_box.getPrd_qty() - 1);
		}

		if (ret_box.getPrd_qty().equals(0)) {
			ret_box.setBnk_flg(BANK_OUT);
		}
		retBoxDao.update(ret_box);

		return new SimpleRtnBeen(ret_box);
	}

	/**
	 * ret_prd_info ret_prd_info
	 * 
	 * @param ret_prd_info
	 * @return
	 */
	private SimpleRtnBeen delRetPrdInfoForCancelUnpack(Ret_prd_info ret_prd_info) {
		ret_prd_info.setEvt_timestamp(gEvtTimestamp);
		ret_prd_info.setEvt_time_d(gEvtTimeD);
		ret_prd_info.setEvt_usr(inTrx.getEvt_usr());
		ret_prd_info.setEvt_cate(EVT_CANCEL_UNPACK);
		retPrdInfoDao.delete(ret_prd_info);
		return new SimpleRtnBeen(_NORMAL);
	}

	/**
	 * Reset ret_wo
	 * 
	 * @param wo_id_fk
	 * @return
	 */
	private SimpleRtnBeen resetRetWoForCancelUnpack(String wo_id_fk) {
		Ret_wo ret_wo = new Ret_wo();

		ret_wo = retWoDao.getWithLock(wo_id_fk,LockMode.UPGRADE);
		if (null == ret_wo) {
			gszMsgBuf = new NotFoundRtnBeen(wo_id_fk, Ret_wo.class).toString();
			return new SimpleRtnBeen(E_RET_WO + E_READ_NOT_FOUND);
		}

		ret_wo.setRl_prd_qty(ret_wo.getRl_prd_qty() - 1);
		retWoDao.update(ret_wo);

		return new SimpleRtnBeen(ret_wo);
	}

	/**
	 * Delete defect info
	 * 
	 * @param prd_seq_id
	 * @return
	 */
	private SimpleRtnBeen delDefForCancelUnpack(String prd_seq_id) {
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		rtnBeen = retPrdJgeDao.delAllDefByPrdId(prd_seq_id);
		if (_NORMAL != rtnBeen.getlRc()) {
			return rtnBeen;
		}
		return rtnBeen;
	}

	private void setOutTrxForCancelUnpack(String ret_prd_id  ,
			Ret_wo ret_wo , Ret_prd_in ret_prd_in) {
		outTrx.setPrd_seq_id(ret_prd_id);
		outTrx.setEvt_timestamp(gEvtTimestamp.toString());
		outTrx.setEvt_usr(inTrx.getEvt_usr());
		outTrx.setFrom_thickness(ret_wo.getFrom_thickness());
		outTrx.setTo_thickness(ret_wo.getTo_thickness());
		outTrx.setPln_prd_qty(ret_wo.getPln_prd_qty());
		outTrx.setRl_prd_qty(ret_wo.getRl_prd_qty());
		outTrx.setRet_prd_in(ret_prd_in);
	}

	/**
	 * 自动创建产品ID，检查RET_PRD_INDT
	 */
	private String creatPrd(Ret_wo ret_wo) {
		String prdKey = ret_wo.getCus_id_fk() + ret_wo.getWo_id();		
		return retPrdIndtDao.createPrdIdLoop(prdKey);
	}
	
	/**
	 * 新增prd grd info表
	 */
	private SimpleRtnBeen addPrdGrdInfoForUnpack(Ret_wo ret_wo,String ret_seq_id) {
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		Integer pnl_std_pnl = 0;
		String prd_seq_grd = "";
		String prd_seq_grd_t = "";
		String prd_seq_grd_c = "";
		Ret_prd_grd_info prd_grd_info = new Ret_prd_grd_info();
		pnl_std_pnl = Integer.valueOf(inTrx.getX_axis_cnt())
			* Integer.valueOf(inTrx.getY_axis_cnt());
		prd_grd_info.setPrd_seq_id_fk(ret_seq_id);
		prd_grd_info.setMdl_id_fk(ret_wo.getMdl_id_fk());
		for(int i=0 ; i<pnl_std_pnl; i++){
			prd_seq_grd = prd_seq_grd + "O";
			prd_seq_grd_t = prd_seq_grd_t + "O";
			prd_seq_grd_c = prd_seq_grd_c + "O";
		}
		prd_grd_info.setPrd_seq_grd(prd_seq_grd);
		prd_grd_info.setPrd_seq_grd_t(prd_seq_grd_t);
		prd_grd_info.setPrd_seq_grd_c(prd_seq_grd_c);
		prd_grd_info.setEvt_usr(inTrx.getEvt_usr());
		prd_grd_info.setEvt_timestamp(gEvtTimestamp);
		prd_grd_info.setPrd_qty(pnl_std_pnl);
		prd_grd_info.setPrd_std_qty(pnl_std_pnl);
		prd_grd_info.setLayot_id_fk(inTrx.getLayot_id());
		prd_grd_info.setX_axis_cnt_fk(Integer.valueOf(inTrx.getX_axis_cnt()));
		prd_grd_info.setY_axis_cnt_fk(Integer.valueOf(inTrx.getY_axis_cnt()));
		prd_grd_info.setCus_ng_qty(0);
		prd_grd_info.setProc_ng_qty(0);
		prd_grd_info.setAct_cus_ng_qty(0);
		prd_grd_info.setAct_proc_ng_qty(0);
		retPrdGrdInfoDao.save(prd_grd_info);
		return rtnBeen;
	}
	
	/**
	 * 删除prd grd info
	 */
	private SimpleRtnBeen delRetGrdInfoForCancelUnpack() {
		Ret_prd_grd_info prd_grd_info = new Ret_prd_grd_info();
		prd_grd_info = retPrdGrdInfoDao.get(inTrx.getPrd_seq_id());
		if(prd_grd_info != null){
			retPrdGrdInfoDao.delete(prd_grd_info);
		}
		return new SimpleRtnBeen(_NORMAL);
	}
	
	/**
	 * 获取RET_CUS_PRD_IN信息
	 * 客户订单，必须有客户来料
	 * 非客户订单，不能提配客户来料
	 */
	private SimpleRtnBeen retCusPrdInCheck(Ret_wo ret_wo){
		Ret_cus_prd_in ret_cus_prd_in = new Ret_cus_prd_in();
		ret_cus_prd_in = retCusPrdInDao.get(inTrx.getMtrl_box_id());
		if(_YES.equals(ret_wo.getSwh_cnt_flg())){//客户订单
			if(ret_cus_prd_in == null){//无客户来料信息则提示报错信息
				gszMsgBuf = "内部订单号 [" + ret_wo.getWo_id() + "]为客户订单，来料箱号必须为客户来料!";
				return new SimpleRtnBeen(E_XPUNPACK_INVALID_BOX_ID);
			}else{//有客户来料信息，返回来料信息
				return new SimpleRtnBeen(ret_cus_prd_in);
			}
		}else{//非客户订单
			if(ret_cus_prd_in != null){//有客户来料信息，则返回提示错误信息
				gszMsgBuf = "内部订单号 [" + ret_wo.getWo_id() + "]为非客户订单，来料箱号不允许为客户来料!";
				return new SimpleRtnBeen(E_XPUNPACK_INVALID_BOX_ID);
			}else{
				return new SimpleRtnBeen(_NORMAL);
			}
		}
	}
	
	/**
	 * 获取RET_CUS_PRD_INDT信息
	 * 客户订单，必须有客户来料
	 * 非客户订单，不能提配客户来料
	 */
	private SimpleRtnBeen retCusPrdIndtCheck(String prdId, Ret_wo ret_wo){
		Ret_cus_prd_indt ret_cus_prd_indt = new Ret_cus_prd_indt();
		ret_cus_prd_indt = retCusPrdIndtDao.get(prdId);
		if(_YES.equals(ret_wo.getSwh_cnt_flg())){//客户订单
			if(ret_cus_prd_indt == null){//无客户来料信息则提示报错信息
				gszMsgBuf = "内部订单号 [" + ret_wo.getWo_id() + "]为客户订单，产品ID必须为客户来料!";
				return new SimpleRtnBeen(E_XPUNPACK_INVALID_PRD_ID);
			}else{//有客户来料信息，返回来料信息
				if(!ret_cus_prd_indt.getMtrl_box_id().equals(inTrx.getMtrl_box_id())){
					gszMsgBuf = "来料箱不匹配，产品ID[" + prdId + "]来料箱[" 
						+ ret_cus_prd_indt.getMtrl_box_id() + "]vs[" 
						+ inTrx.getMtrl_box_id() + "]!";
					return new SimpleRtnBeen(E_XPUNPACK_MTRL_BOX_INVALIED);
				}else{
					return new SimpleRtnBeen(ret_cus_prd_indt);
				}
			}
		}else{//非客户订单
			if(ret_cus_prd_indt != null){//有客户来料信息，则返回提示错误信息
				gszMsgBuf = "内部订单号 [" + ret_wo.getWo_id() + "]为非客户订单，产品ID不允许为客户来料!";
				return new SimpleRtnBeen(E_XPUNPACK_INVALID_PRD_ID);
			}else{
				return new SimpleRtnBeen(_NORMAL);
			}
		}
	}
	
	/**
	 * Get & check prd_info for cancel unpack
	 * 
	 * @param prd_seq_id
	 * @return {Ret_prd_info}
	 */
	private SimpleRtnBeen ResetPrdLotInfoForCancelUnpack(String prd_seq_id) {
		Ret_prd_info ret_prd_info = new Ret_prd_info();

		ret_prd_info = retPrdInfoDao.get(prd_seq_id);
		if (null == ret_prd_info) {
			gszMsgBuf = new NotFoundRtnBeen(prd_seq_id, Ret_prd_info.class)
					.toString();
			return new SimpleRtnBeen(E_RET_PRD_INFO + E_READ_NOT_FOUND);
		}

		// lot_id
		if (Util.isSpaceCheck(ret_prd_info.getLot_id())) {
			return new SimpleRtnBeen(ret_prd_info);
		}
		
		String sql = "FROM Ret_prd_lot where lot_id = '"+ret_prd_info.getLot_id()+"'";
		List<Ret_prd_lot> lotList = new ArrayList<Ret_prd_lot>();
		lotList = retPrdLotDao.find(sql);
		if ( !lotList.isEmpty() ){
			int lotQty = lotList.get(0).getLot_qty();
			lotList.get(0).setLot_qty(lotQty - 1);
			retPrdLotDao.update(lotList.get(0));
		}
		
		return new SimpleRtnBeen(ret_prd_info);
	}
	
	private long checkXmtmPrdIndtProc() {
		String woId = inTrx.getWo_id();
		String shtId = inTrx.getPrd_seq_id();
		
		Ret_wo retWo = retWoDao.get(woId);
		String cusId = retWo.getCus_id_fk();
		
		boolean isXMTMProd = bisDataDao.checkEdiCusProc("XMTM",cusId);
		if(isXMTMProd){
			String boxId = inTrx.getBox_id();
			Ret_tm_cus_prd_in tmBox = retTmCusPrdInDao.get(boxId);
			if(tmBox != null){
				Ret_tm_cus_prd_indt retTmCusPrdindt = retTmCusPrdIndtDao.get(shtId);
				outTrx.setHas_custom_material_flg(retTmCusPrdindt == null ? "N" : "Y");
			}
		}else{
			outTrx.setHas_custom_material_flg("Y");
		}
		outTrx.setOut_control_flg("N");
	if(inTrx.getOut_chk_flg().equals("Y")){
		Bis_mdl_def bis_mdl_def = bisMdlDefDao.get(retWo.getMdl_id_fk());
		if(!Util.isSpaceCheck(bis_mdl_def.getMdl_param())){
			List<Bis_data> dataList = new ArrayList<Bis_data>();
			String hql = "FROM Bis_data where data_cate = 'PRDM' and data_id = '" + bis_mdl_def.getMdl_param() + "'" ;	
			dataList = bisDataDao.find(hql);
			if(!dataList.isEmpty()){
				for(Bis_data bis_data: dataList){
					String data_ext = bis_data.getData_ext();
					String ext_1 = bis_data.getExt_1();
					String[] sub = data_ext.split(",");
					String[] chr = ext_1.split(",");
					String has_flg = "N";
					if(shtId.length()<Integer.valueOf(sub[1])){
						continue;
					}
					for(int i=0; i<chr.length; i++){
						if(shtId.substring(Integer.valueOf(sub[0]), Integer.valueOf(sub[1])).equals(chr[i])){
							has_flg = "Y";
							break;
						}
					}
					if(has_flg.equals("N")){
						outTrx.setOut_control_flg("Y");
						break;
					}
				}
			}
		}
	}
		outTrx.setRtn_code(RETURN_CODE_OK);
		outTrx.setRtn_mesg(RETURN_MESG_OK);
		return 0;
	}

	
}
